﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace RolePlayingGame
{
    public class Engine
    {
        private readonly int width;
        private readonly int height;
        private readonly int playerChoice;

        private IRenderer renderer;
        private PlayerBase player;
        List<MapObject> fieldObjects = new List<MapObject>();

        public Engine(int width, int height, int playerChoice, IRenderer renderer)
        {
            this.renderer = renderer;
            this.width = width;
            this.height = height;
            this.playerChoice = playerChoice;

            Coord initialPlayerCoords = new Coord(5, height - 1);
            switch (playerChoice)
            {
                case 1: player = new PlayerCardinal(initialPlayerCoords); break;
                case 2: player = new PlayerString(initialPlayerCoords); break;
                case 3: player = new PlayerSpeedy(initialPlayerCoords); break;
                default: throw new InvalidInputException("Only 3 player types are currently implemented");
            }

        }

        public void Run()
        {

            

            const int enemiesPerLevel = 10;
            int enemiesCount = player.Level * enemiesPerLevel;
            EnemyBase[] enemies = new EnemyBase[enemiesCount];
            int enemiesLived = 0;
            Random rndPosition = new Random();

            fieldObjects.Add(new EnemyBool(new Coord(3, 1), 1)); //Test Code<<<<<<<<<<<<<<<<<<<<<<<<<<

            while (player.Health > 0)
            {

                CheckCollisions();

                RecieveCommand();

                this.renderer.ClearQueue();

                this.renderer.EnqueueForRendering(player);
                foreach (var item in fieldObjects)
                {
                    this.renderer.EnqueueForRendering(item);
                }


                this.renderer.RenderAll();

                Thread.Sleep(100);

            }


        }

        private void CheckCollisions()
        {
            
            for (int i = 0; i < fieldObjects.Count; i++)
            {
                for (int j = i+1; j < fieldObjects.Count; j++)
                {
                    if (fieldObjects[i].Location.X != fieldObjects[j].Location.X) continue;
                    if (fieldObjects[i].Location.Y != fieldObjects[j].Location.Y) continue;
                    fieldObjects[i].CollideWith(fieldObjects[j]);
                }
            }
        }

        private void RecieveCommand()
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo keyInfo = Console.ReadKey(true);
                while (Console.KeyAvailable)
                {
                    Console.ReadKey(true);
                }
                if (keyInfo.Key == ConsoleKey.LeftArrow)
                {
                    if (player.Location.X > 0) 
                    {
                        player.Move(new Coord(-1, 0));
                    }
                }
                else if (keyInfo.Key == ConsoleKey.RightArrow)
                {
                    if (player.Location.X < (width - 1))
                    {
                        player.Move(new Coord(1, 0));
                    }
                }
                if (keyInfo.Key == ConsoleKey.Spacebar)
                {
                    fieldObjects.Add(player.Shoot());
                }
                else if (keyInfo.Key == ConsoleKey.Backspace)
                {
                    throw new NotImplementedException("Cast Special Ability");
                }
                else if (keyInfo.Key == ConsoleKey.P)
                {
                    PauseGame();
                }
            }
        }

        private void PauseGame()
        {
            while (true)
            {
                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo keyInfo = Console.ReadKey(true);
                    while (Console.KeyAvailable)
                    {
                        Console.ReadKey(true);
                    }
                    if (keyInfo.Key == ConsoleKey.R)
                    {
                        return;
                    }
                }
            }
        }

        public void StartGame()
        {
            //TODO

            //user's choice
        }

        public void SaveGame()
        {
            //Save the current
            //      - diplayed player, item, enemy properties(location, health, weapons, armour etc.) (i.e. the screen data)
            //      - the number of the first line in the map.txt file which has not been read yet(i.e. where to start MapInterpreter() from)
            //

        }

        public void LoadGame()
        {
            //TODO
        }

        public void CollisionChecker()
        {
            throw new NotImplementedException("List<>object is Missing; ICollidable is not implemented yet.");
            //List<MapObject> or List<ICollidable> fieldedObjects
            //foreach (var first in this.fieldedObjects)
            //{
            //    foreach (var second in this.fieldedObjects)
            //    {
            //        if (first == second) continue;

            //        if (first.Location == second.Location)
            //        {
            //            Collide(first, second);  //Do not change objects in the Collide method
            //                                     //simply add them (by reference) to a List<>collided for modification
            //                                     //then at the end -> Modify collided
            //        }
            //    }
            //}

            //ModifyCollided();
        }

        private void ModifyCollided()
        {
            throw new NotImplementedException("List<>object is Missing; ICollidable is not implemented yet.");

            //for (int i = 0; i < this.collided.Count; i++)
            //{

            //}
        }

    }
}
